/*
 *  author: Honrun
 *  date:   2021/12/25 11:30
 */
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "stm32f1xx_hal.h"
#include "DevicesQueue.h"
#include "DevicesTime.h"
#include "DevicesNEC.h"

NecCodeType g_typeNecDecode = {0};

void vNecIRInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    /* Enable GPIOA clock */
    __HAL_RCC_GPIOE_CLK_ENABLE();

    /* Configure PA.00 pin as input floating */
    GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Pin = GPIO_PIN_14;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);

    /* Enable and set EXTI line 0 Interrupt to the lowest priority */
    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

int8_t cNecDecode(NecCodeType *ptypeData, int16_t sValue)
{
    uint8_t ucValue = 0;

    if((sValue > NEC_CODE_LOW_MIN) && (sValue < NEC_CODE_LOW_MAX))
        ucValue = 0;
    else if((sValue > NEC_CODE_HIGH_MIN) && (sValue < NEC_CODE_HIGH_MAX))
        ucValue = 1;
    else
        ptypeData->state = necReset;

    ++ptypeData->length;

    switch(ptypeData->state)
    {
        case necReset:
            memset(ptypeData, 0, sizeof(NecCodeType));
            ptypeData->state = necReadUser;
            break;

        case necReadUser:
            ptypeData->user = (ptypeData->user << 1) | ucValue;
            if(ptypeData->length >= 8)
                ptypeData->state = necReadControl;
            break;

        case necReadControl:
            ptypeData->control = (ptypeData->control << 1) | ucValue;
            if(ptypeData->length >= 16)
                ptypeData->state = necReadData;
            break;

        case necReadData:
            if(ptypeData->control == 0x55)
            {
                ptypeData->data = (ptypeData->data << 1) | ucValue;
                if(ptypeData->length >= 32)
                    ptypeData->state = necSucceed;
            }
            else
            {
                /* 低位先发送、先接收 */
                ptypeData->data |= ucValue << (ptypeData->length - 17);
                if(ptypeData->length >= 48)
                    ptypeData->state = necSucceed;
            }
            break;

        default: ptypeData->state = necReadUser; break;
    }

    if(ptypeData->state == necSucceed)
        printf("length: %d, user: %02X, control: %02X, data: %08X\r\n", ptypeData->length, ptypeData->user, ptypeData->control, ptypeData->data);

    return ptypeData->state;
}

void EXTI15_10_IRQHandler(void)
{
    static int64_t st_NecIRTimeLast = 0;
    int64_t st_NecIRTimeNow = 0;
    int16_t sTime = 0;

    /* EXTI line interrupt detected */
    if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_14) != 0)
    {
        st_NecIRTimeNow = lTimeGetStamp();

        sTime = ((st_NecIRTimeNow - st_NecIRTimeLast) < 0x7FFF) ? st_NecIRTimeNow - st_NecIRTimeLast : 0x7FFF;

        st_NecIRTimeLast = st_NecIRTimeNow;

        enumQueuePushDatas(&g_TypeQueueIR2_4GInput, (uint8_t *)&sTime, sizeof(sTime));

        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_14);
    }
}
